<script setup>
import { ref, onMounted } from "vue";
import { ElMessage } from "element-plus";
import { userInfoStore } from "@/stores/user";
import {addUserAuth, getFaceAuth, getUserAuth, registerFace} from "@/apis/auth";
import { uploadImg } from "@/apis/upload";

onMounted(async () => {
  await getUserAuthStatus();
  await getFaceAuthStatus();
});

const userInfo = userInfoStore().userInfo;

// 状态变量
const personalAuthStatus = ref(false); // 个人认证状态
const faceAuthStatus = ref(false); // 人脸识别状态
const userAvatar = ref(userInfo.avatarUrl); // 默认头像

const getUserAuthStatus = async () => {
  const res = await getUserAuth();
  console.log("res: ", res);
  personalAuthStatus.value = res.data;
};
const getFaceAuthStatus = async () => {
  const res = await getFaceAuth();
  console.log("res: ", res);
  faceAuthStatus.value = res.data;
};

// 是否显示认证区域
const showPersonalAuth = ref(false);
const showFaceAuth = ref(false);

const idCardName = ref("");
const idCardNumber = ref("");

// 证件图片链接
const idCardFront = ref(null);
const idCardBack = ref(null);
const studentCardFront = ref(null);
const studentCardBack = ref(null);
const faceFiles = ref([]);

// 上传前验证
const beforeUpload = (file) => {
  const isImage = file.type.startsWith("image/");
  if (!isImage) {
    ElMessage.error("只能上传图片文件");
    return false;
  }
  const isLt2M = file.size / 1024 / 1024 < 5;
  if (!isLt2M) {
    ElMessage.error("图片大小不能超过 2MB");
    return false;
  }
  return true;
};

// 上传图片
const uploadImage = async (options, fileType) => {
  const { file } = options;
  const formData = new FormData();
  formData.append("file", file);

  try {
    const res = await uploadImg(formData);
    if (res.code === 200) {
      // 根据 fileType 设置对应的图片链接
      if (fileType === "idCardFront") {
        idCardFront.value = res.message;
      } else if (fileType === "idCardBack") {
        idCardBack.value = res.message;
      } else if (fileType === "studentCardFront") {
        studentCardFront.value = res.message;
      } else if (fileType === "studentCardBack") {
        studentCardBack.value = res.message;
      }

      ElMessage.success("上传成功");
    } else {
      ElMessage.error("上传失败");
    }
  } catch (error) {
    ElMessage.error("上传出错");
    console.error(error);
  }
};

// 上传人脸照片
// 移除图片
const handleRemoveImage = (fileType, file, fileList) => {
  if (fileType === "idCardFront" && idCardFront.value === file.url) {
    idCardFront.value = null;
  } else if (fileType === "idCardBack" && idCardBack.value === file.url) {
    idCardBack.value = null;
  } else if (fileType === "studentCardFront" && studentCardFront.value === file.url) {
    studentCardFront.value = null;
  } else if (fileType === "studentCardBack" && studentCardBack.value === file.url) {
    studentCardBack.value = null;
  }
};

// 上传失败回调
const handleUploadError = (err) => {
  ElMessage.error(`上传失败: ${err.message}`);
};

// 切换个人认证显示
const togglePersonalAuth = () => {
  if (!personalAuthStatus.value) {
    showPersonalAuth.value = !showPersonalAuth.value;
    showFaceAuth.value = false;
  }
};

const submitPersonalAuth = async () => {
  const res = await addUserAuth({
    userId: userInfoStore().userInfo.userId,
    idCardName: idCardName.value,
    idCardNumber: idCardNumber.value,
    idCardFront: idCardFront.value,
    idCardBack: idCardBack.value,
    studentCardFront: studentCardFront.value,
    studentCardBack: studentCardBack.value,
  });

  if (res.code === 200) {
    idCardName.value = "";
    idCardNumber.value = "";
    idCardFront.value = "";
    idCardBack.value = "";
    studentCardFront.value = "";
    studentCardBack.value = "";
    showFaceAuth.value = false;
    ElMessage.success("提交成功");
  }
};

// 切换人脸识别显示
const toggleFaceAuth = () => {
  if (!faceAuthStatus.value) {
    showFaceAuth.value = !showFaceAuth.value;
    showPersonalAuth.value = false;
  }
};

// 摄像头和裁剪相关变量
const videoElement = ref(null);
const cropper = ref(null);
const cameraActive = ref(false);
const faceImageUploaded = ref(false);
const cameraError = ref(false);
const faceImagePreview = ref(null);
const faceFile = ref(null);
const faceImageUrl = ref(null);
const croppedImage = ref(null);
const cropSize = ref(150);
const cropLeft = ref(0);
const cropTop = ref(0);
const cropWidth = ref(300);
const cropHeight = ref(300);
const isCropping = ref(false);
const startX = ref(0);
const startY = ref(0);
const startLeft = ref(0);
const startTop = ref(0);
const faceImage = ref(null);

// 摄像头相关方法
const startCamera = async () => {
  try {
    const stream = await navigator.mediaDevices.getUserMedia({ video: true });
    videoElement.value.srcObject = stream;
    videoElement.value.play();
    cameraActive.value = true;
    cameraError.value = false;
  } catch (error) {
    console.error("摄像头错误:", error);
    cameraError.value = true;
    ElMessage.error("无法访问摄像头，请检查权限设置");
  }
};

const stopCamera = () => {
  const tracks = videoElement.value.srcObject.getTracks();
  tracks.forEach((track) => track.stop());
  videoElement.value.srcObject = null;
  cameraActive.value = false;
};

const capturePhoto = () => {
  const canvas = document.createElement("canvas");
  const context = canvas.getContext("2d");
  canvas.width = videoElement.value.videoWidth;
  canvas.height = videoElement.value.videoHeight;
  context.drawImage(videoElement.value, 0, 0, canvas.width, canvas.height);

  const dataUrl = canvas.toDataURL("image/jpeg");
  console.log("dataUrl: ", dataUrl);
  faceImagePreview.value = dataUrl;
  faceImageUploaded.value = true;

  // 设置 faceFile 和 faceImageUrl，以便复用上传图片后的裁剪逻辑
  faceFile.value = dataURLtoFile(dataUrl, "captured-face.jpg");
  faceImageUrl.value = dataUrl;

  cameraActive.value = false;
  stopCamera();
};

// 从文件上传图片
const handleFileChange = (file) => {
  if (file.raw) {
    faceFile.value = file.raw;
    faceImageUrl.value = URL.createObjectURL(faceFile.value);

    // 在图片加载完成后设置裁剪框的初始大小和位置
    const image = new Image();
    image.onload = () => {
      console.log("image: ", image);
      const naturalWidth = image.naturalWidth;
      const naturalHeight = image.naturalHeight;

      // 将图片元素的宽高设置为自然宽高
      image.width = naturalWidth;
      image.height = naturalHeight;

      // 设置裁剪框的初始大小为图片宽度和高度的一半
      cropWidth.value = naturalWidth / 2;
      cropHeight.value = naturalHeight / 2;

      // 设置裁剪框的初始位置为图片的中心
      cropLeft.value = (naturalWidth - cropWidth.value) / 2;
      cropTop.value = (naturalHeight - cropHeight.value) / 2;
    };
    image.src = faceImageUrl.value;
    ElMessage.success("人脸照片上传成功");
  }
};

// 裁剪框相关方法
const startCrop = (event) => {
  console.log("event: ", event);
  isCropping.value = true;
  const e = event.type.includes("touch") ? event.touches[0] : event;
  startX.value = e.clientX;
  startY.value = e.clientY;
  startLeft.value = cropLeft.value;
  startTop.value = cropTop.value;

  window.addEventListener("mousemove", moveCrop);
  window.addEventListener("touchmove", moveCrop, { passive: false });
  window.addEventListener("mouseup", endCrop);
  window.addEventListener("touchend", endCrop);
};
const moveCrop = (event) => {
  if (!isCropping.value) return;
  const e = event.type.includes("touch") ? event.touches[0] : event;

  const dx = e.clientX - startX.value;
  const dy = e.clientY - startY.value;

  const image = faceImage.value;
  if (image) {
    const maxLeft = image.naturalWidth - cropWidth.value;
    const maxTop = image.naturalHeight - cropHeight.value;

    cropLeft.value = Math.max(0, Math.min(startLeft.value + dx, maxLeft));
    cropTop.value = Math.max(0, Math.min(startTop.value + dy, maxTop));
  }
};
const endCrop = () => {
  isCropping.value = false;
  window.removeEventListener("mousemove", moveCrop);
  window.removeEventListener("touchmove", moveCrop);
  window.removeEventListener("mouseup", endCrop);
  window.removeEventListener("touchend", endCrop);
};
const updateCropSize = () => {
  cropWidth.value = cropSize.value;
  cropHeight.value = cropSize.value;
};
const resetCrop = () => {
  // cropSize.value = 150;
  // updateCropSize();
  cropLeft.value = 0;
  cropTop.value = 0;
  croppedImage.value = null;
};
const cropFace = () => {
  const image = faceImage.value;
  if (image) {
    const canvas = document.createElement("canvas");
    const context = canvas.getContext("2d");

    // 设置画布大小为裁剪框的大小
    canvas.width = cropWidth.value;
    canvas.height = cropHeight.value;

    // 绘制裁剪区域到画布
    context.drawImage(
      image,
      cropLeft.value,
      cropTop.value,
      cropWidth.value,
      cropHeight.value,
      0,
      0,
      canvas.width,
      canvas.height
    );

    const croppedDataUrl = canvas.toDataURL("image/jpeg");
    croppedImage.value = croppedDataUrl;
    ElMessage.success("裁剪成功");
  }
};

const submitFaceAuth = async () => {
  if (!croppedImage.value) {
    ElMessage.error("请先裁剪图片");
    return;
  }

  const fileName = "cropped-face.jpg";
  const file = dataURLtoFile(croppedImage.value, fileName);
  const formData = new FormData();
  formData.append("file", file);

  try {
    // const res = await uploadImg(formData);
    if (formData) {
      const registerFaceRes = await registerFace(formData);
      console.log("registerFace ", registerFaceRes);
      if (registerFaceRes.code === 200) {
        ElMessage.success("人脸识别提交成功");
        faceFiles.value = [];
        faceImagePreview.value = null;
        faceFile.value = null;
        faceImageUrl.value = null;
        croppedImage.value = null;
        showFaceAuth.value = false;
      } else {
        ElMessage.error("人脸识别提交失败");
      }
    } else {
      ElMessage.error("图片上传失败");
    }
  } catch (error) {
    ElMessage.error("上传出错");
    console.error(error);
  }
};

const dataURLtoFile = (dataurl, filename) => {
  const arr = dataurl.split(",");
  const mime = arr[0].match(/:(.*?);/)[1];
  const bstr = atob(arr[1]);
  let n = bstr.length;
  const u8arr = new Uint8Array(n);

  while (n--) {
    u8arr[n] = bstr.charCodeAt(n);
  }

  return new File([u8arr], filename, { type: mime });
};

const resetPhoto = () => {
  // 清除当前的图片状态
  faceImagePreview.value = null;
  faceFile.value = null;
  faceImageUrl.value = null;
  croppedImage.value = null;

  // 重置摄像头相关状态
  cameraError.value = false; // 关闭摄像头错误提示
  faceImageUploaded.value = false; // 确保不在上传图片的区域

  // 重新打开摄像头
  startCamera();
};
</script>

<template>
  <div class="authentication-page">
    <el-card class="auth-card">
      <!-- 第一行：个人头像 -->
      <div class="avatar-container" style="text-align: center">
        <el-avatar :size="100" :src="userAvatar" />
      </div>

      <!-- 第二行：个人认证状态 -->
      <el-row class="auth-row" justify="space-between">
        <el-col :span="6" :offset="6">
          <div class="auth-title">个人认证</div>
        </el-col>
        <el-col :span="6" :offset="6">
          <el-tag
            :type="personalAuthStatus ? 'success' : 'info'"
            effect="dark"
            @click="togglePersonalAuth"
          >
            {{ personalAuthStatus ? "已认证" : "未认证" }}
          </el-tag>
        </el-col>
      </el-row>

      <!-- 第三行：人脸识别状态 -->
      <el-row class="auth-row" justify="space-between">
        <el-col :span="6" :offset="6">
          <div class="auth-title">人脸识别</div>
        </el-col>
        <el-col :span="6" :offset="6">
          <el-tag
            :type="faceAuthStatus ? 'success' : 'info'"
            effect="dark"
            @click="toggleFaceAuth"
          >
            {{ faceAuthStatus ? "已认证" : "未认证" }}
          </el-tag>
        </el-col>
      </el-row>

      <!-- 个人认证上传区域 -->
      <div v-if="showPersonalAuth" class="upload-container">
        <h3>个人认证</h3>
        <div style="padding: 20px 0; width: 100%">
          <el-input v-model="idCardName" style="width: 200px" placeholder="真实姓名" />
          <el-input
            v-model="idCardNumber"
            style="width: 400px; margin-left: 20px"
            placeholder="身份证号"
          />
        </div>
        <div
          style="
            display: flex;
            justify-content: flex-start;
            align-items: center;
            gap: 20px;
          "
        >
          <div class="upload-item">
            <div class="upload-title">身份证正面</div>
            <el-upload
              class="upload-demo"
              action=""
              :http-request="(options) => uploadImage(options, 'idCardFront')"
              :on-success="handleUploadSuccess"
              :on-remove="
                (file, fileList) => handleRemoveImage('idCardFront', file, fileList)
              "
              :on-exceed="handleExceed"
              :before-upload="beforeUpload"
              :show-file-list="false"
            >
              <img v-if="idCardFront" :src="idCardFront" class="avatar" />
              <div v-else class="img-box">
                <el-icon class="avatar-uploader-icon" size="36"><Plus /></el-icon>
                <div class="el-upload__text">点击上传身份证正面</div>
              </div>
            </el-upload>
          </div>

          <div class="upload-item">
            <div class="upload-title">身份证反面</div>
            <el-upload
              class="upload-demo"
              action=""
              :http-request="(options) => uploadImage(options, 'idCardBack')"
              :on-success="handleUploadSuccess"
              :on-remove="
                (file, fileList) => handleRemoveImage('idCardBack', file, fileList)
              "
              :on-exceed="handleExceed"
              :before-upload="beforeUpload"
              :show-file-list="false"
            >
              <img v-if="idCardBack" :src="idCardBack" class="avatar" />
              <div v-else class="img-box">
                <el-icon class="avatar-uploader-icon" size="36"><Plus /></el-icon>
                <div class="el-upload__text">点击上传身份证反面</div>
              </div>
            </el-upload>
          </div>
        </div>

        <div
          style="
            display: flex;
            justify-content: flex-start;
            align-items: center;
            gap: 20px;
          "
        >
          <div class="upload-item">
            <div class="upload-title">学生证正面</div>
            <el-upload
              class="upload-demo"
              action=""
              :http-request="(options) => uploadImage(options, 'studentCardFront')"
              :on-success="handleUploadSuccess"
              :on-remove="
                (file, fileList) => handleRemoveImage('studentCardFront', file, fileList)
              "
              :on-exceed="handleExceed"
              :before-upload="beforeUpload"
              :show-file-list="false"
            >
              <img v-if="studentCardFront" :src="studentCardFront" class="avatar" />
              <div v-else class="img-box">
                <el-icon class="avatar-uploader-icon" size="36"><Plus /></el-icon>
                <div class="el-upload__text">点击上传学生证正面</div>
              </div>
            </el-upload>
          </div>

          <div class="upload-item">
            <div class="upload-title">学生证反面</div>
            <el-upload
              class="upload-demo"
              action=""
              :http-request="(options) => uploadImage(options, 'studentCardBack')"
              :on-success="handleUploadSuccess"
              :on-remove="
                (file, fileList) => handleRemoveImage('studentCardBack', file, fileList)
              "
              :on-exceed="handleExceed"
              :before-upload="beforeUpload"
              :show-file-list="false"
            >
              <img v-if="studentCardBack" :src="studentCardBack" class="avatar" />
              <div v-else class="img-box">
                <el-icon class="avatar-uploader-icon" size="36"><Plus /></el-icon>
                <div class="el-upload__text">点击上传学生证反面</div>
              </div>
            </el-upload>
          </div>
        </div>
        <div class="submit-container">
          <el-button type="primary" @click="submitPersonalAuth">提交个人认证</el-button>
        </div>
      </div>

      <!-- 人脸识别上传区域 -->
      <div v-if="showFaceAuth" class="upload-container">
        <h3>人脸识别</h3>

        <!-- 摄像头拍摄区域 -->
        <div v-if="!faceImageUploaded && !cameraError" class="camera-container">
          <div class="camera-area">
            <video
              ref="videoElement"
              autoplay
              playsinline
              style="width: 100%; height: 300px; background-color: #000"
            ></video>
            <div class="camera-buttons">
              <el-button type="primary" @click="startCamera" :disabled="cameraActive">
                打开摄像头
              </el-button>
              <el-button type="success" @click="capturePhoto" v-if="cameraActive">
                拍摄
              </el-button>
              <el-button type="danger" @click="stopCamera" v-if="cameraActive">
                停止
              </el-button>
            </div>
          </div>
        </div>

        <!-- 如果摄像头出错，显示上传组件 -->
        <div v-if="cameraError" class="upload-fallback">
          <el-alert
            title="摄像头无法使用"
            type="warning"
            description="您的设备摄像头不可用或被拒接访问，请通过上传图片完成人脸识别"
            show-icon
          />
          <div class="upload-item">
            <div class="upload-title">上传人脸照片</div>
            <el-upload
              class="upload-demo"
              :auto-upload="false"
              :file-list="faceFiles"
              :limit="1"
              drag
              multiple
              :accept="'.jpg,.jpeg,.png'"
              :before-upload="beforeUpload"
              @change="handleFileChange"
            >
              <i class="el-icon-upload"></i>
              <div class="el-upload__text">点击或拖拽上传人脸照片</div>
            </el-upload>
          </div>
        </div>

        <div v-if="faceFile" class="crop-container">
          <div class="crop-title">框选人脸区域</div>
          <div class="image-container">
            <img
              ref="faceImage"
              :src="faceImageUrl"
              alt="人脸照片"
              style="display: block; margin: 0 auto"
            />
            <div
              class="crop-frame"
              v-if="faceFile"
              :style="{
                width: `${cropWidth}px`,
                height: `${cropHeight}px`,
                left: `${cropLeft}px`,
                top: `${cropTop}px`,
              }"
              @mousedown="startCrop"
              @touchstart="startCrop"
            ></div>
          </div>
          <div class="crop-controls">
            <el-button type="success" @click="resetPhoto"> 重新拍摄 </el-button>
            <el-button @click="cropFace">裁剪</el-button>
            <el-button @click="resetCrop">重置</el-button>
            <el-button type="primary" @click="submitFaceAuth">提交</el-button>
          </div>
          <!-- 裁剪预览区域 -->
          <div class="preview-container" v-if="croppedImage">
            <div class="preview-title">裁剪预览</div>
            <img
              :src="croppedImage"
              alt="裁剪后的图片"
              style="max-width: 300px; max-height: 200px"
            />
          </div>
        </div>
      </div>
    </el-card>
  </div>
</template>

<style scoped lang="scss">
.authentication-page {
  margin: 20px;
}

.auth-card {
  max-width: 800px;
  margin: 0 auto;
}

.avatar-container {
  margin-bottom: 20px;
}

.auth-row {
  margin-bottom: 20px;
  cursor: pointer;
  text-align: left;
}

.auth-title {
  font-weight: bold;
  margin-bottom: 10px;
}

.upload-container {
  margin-top: 30px;
}

.upload-item {
  margin-bottom: 30px;
  img {
    width: 150px;
    height: 150px;
  }
}

.upload-title {
  font-weight: bold;
  margin-bottom: 10px;
}

.img-box {
  width: 150px;
  height: 150px;
  border: 1px dashed #f9f;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  border-radius: 12px;
  gap: 20px;
}

.preview-container {
  margin-top: 10px;
  display: flex;
  flex-wrap: wrap;
}

.crop-container {
  margin-top: 20px;
  text-align: center;
}

.crop-title {
  font-weight: bold;
  margin-bottom: 10px;
}

.crop-buttons {
  margin-top: 10px;
}

.submit-container {
  margin-top: 20px;
}

.camera-container {
  margin-bottom: 20px;
}

.camera-area {
  border: 1px solid #eee;
  border-radius: 8px;
  padding: 15px;
  text-align: center;
}

.camera-buttons {
  margin-top: 15px;
  display: flex;
  justify-content: center;
  gap: 10px;
}

.upload-fallback {
  margin-top: 20px;
}

.image-container {
  position: relative;
  max-width: 800px;
  margin: 0 auto;
  margin-bottom: 20px;
  border: 1px solid #eee;
  padding: 10px;
}

.crop-frame {
  position: absolute;
  border: 2px dashed #409eff;
  background-color: rgba(64, 158, 255, 0.1);
  cursor: move;
}

.crop-controls {
  margin-top: 15px;
}

.crop-buttons {
  margin-top: 15px;
  display: flex;
  justify-content: center;
  gap: 15px;
}

.preview-container {
  margin-top: 20px;
  text-align: center;
}

.preview-title {
  font-weight: bold;
  margin-bottom: 10px;
}
</style>
